package com.example.helloffmpeg.util;

import android.text.TextUtils;
import android.util.Log;
import com.elvishew.xlog.Logger;
import com.elvishew.xlog.flattener.ClassicFlattener;
import com.elvishew.xlog.printer.AndroidPrinter;
import com.elvishew.xlog.printer.Printer;
import com.elvishew.xlog.printer.file.FilePrinter;
import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy;
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator;
import com.example.helloffmpeg.constants.AppConstant;

import java.io.File;

/**
 * Created by luofei on 2017/4/25.
 */

public class LogU {
    private static final String TAG = LogU.class.getSimpleName();
    private static final int V = 1;
    private static final int D = 2;
    private static final int I = 3;
    private static final int W = 4;
    private static final int E = 5;
    private static boolean SHOW_LOG_FLAG = true;  //是否显示log日志
    private static final String LOG_PATH = "/Kandao/QooCam/Log/";
    private static Printer FILE_PRINTER;
    private static final int MAX_TIME = 1000 * 60 * 30; // half hour
    public static boolean SAVE_LOG_TO_FILE_FLAG;

    public static void init() {
        SHOW_LOG_FLAG = true;
        if (SAVE_LOG_TO_FILE_FLAG) {
            FILE_PRINTER = new FilePrinter                      // Printer that print the log to the file system
                    .Builder(new File(AppConstant.ROOT_DIR_PATH, LOG_PATH).getPath())       // Specify the path to save log file
                    .fileNameGenerator(new DateFileNameGenerator())        // Default: ChangelessFileNameGenerator("log")
                    // .backupStrategy(new MyBackupStrategy())             // Default: FileSizeBackupStrategy(1024 * 1024)
                    .cleanStrategy(new FileLastModifiedCleanStrategy(MAX_TIME))     // Default: NeverCleanStrategy()
                    .flattener(new ClassicFlattener())                     // Default: DefaultFlattener
                    .build();
        }
    }

    public static void v(Object obj) {
        log(V, null, obj);
    }

    public static void v(String tag, Object obj) {
        log(V, tag, obj);
    }

    public static void d(Object obj) {
        log(D, null, obj);
    }

    public static void d(String tag, Object obj) {
        log(D, tag, obj);
    }

    public static void i(Object obj) {
        log(I, null, obj);
    }

    public static void i(String tag, Object obj) {
        log(I, tag, obj);
    }

    public static void w(Object obj) {
        log(W, null, obj);
    }

    public static void w(String tag, Object obj) {
        log(W, tag, obj);
    }

    public static void w(String tag, String msg, Object obj) {
        log(W, tag + "[" + msg + "]", obj);
    }

    public static void e(Object obj) {
        log(E, null, obj);
    }

    public static void e(String tag, Object obj) {
        log(E, tag, obj);
    }

    public static void e(String tag, String msg, Object obj) {
        log(E, tag + "[" + msg + "]", obj);
    }

    public static void stack() {
        logStack(null);
    }

    public static void stack(String tag) {
        logStack(tag);
    }

    private static void logStack(String tag) {
        if (SHOW_LOG_FLAG) {
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            int index = 4;
            String className = stackTrace[index].getFileName();//获取类名
            tag = TextUtils.isEmpty(tag) ? className : tag;

            StringBuilder sb = new StringBuilder("Log stack trace\n");
            sb.append("=======================================================================================================================================================")
                    .append("\n");
            for (; index < stackTrace.length; index++) {
                sb.append("|| ").append(stackTrace[index]).append("\n");
            }
            sb.append("=======================================================================================================================================================");
            Log.d(tag, sb.toString());
        }
    }

    public static void log(int type, String tagStr, Object obj) {
        if (!SHOW_LOG_FLAG) {
            return;
        }
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

        int index = 4;
        String className = stackTrace[index].getFileName();//获取类名
        String methodName = stackTrace[index].getMethodName();//获取方法名
        int lineNumber = stackTrace[index].getLineNumber();//获取代码行数

        String tag = (tagStr == null ? className : tagStr);

        StringBuilder sb = new StringBuilder();
        sb.append("[(").append(className).append(":").append(lineNumber).append(") #").append(methodName).append("]");

        if (obj == null) {
            sb.append("Log with null object");
        } else if (obj instanceof Throwable) {
            sb.append("Throwable! Print stack trace--------------\n");
            sb.append(Log.getStackTraceString((Throwable) obj));
        } else {
            sb.append(obj.toString());
        }
        String logStr = sb.toString();
        if (SAVE_LOG_TO_FILE_FLAG) {
            printLog(type, 0, tag, logStr);
        } else {
            switch (type) {
                case V:
                    Log.v(tag, logStr);
                    break;
                case D:
                    Log.d(tag, logStr);
                    break;
                case I:
                    Log.i(tag, logStr);
                    break;
                case W:
                    Log.w(tag, logStr);
                    break;
                case E:
                    Log.e(tag, logStr);
                    break;
            }
        }
    }

    public static void printFloatArray(String tag, float[] array) {
        StringBuilder result = new StringBuilder(tag + " ");
        for (int i = 0; i < array.length; i++) {
            if (i % 4 == 0) {
                result.append(" -- \n");
            }
            result.append(" ").append(array[i]);
        }

        log(D, null, result.toString());
    }

    public static void printIntArray(String tag, int[] array) {
        StringBuilder result = new StringBuilder(tag + " ");
        for (int i = 0; i < array.length; i++) {
            if (i % 4 == 0) {
                result.append(" -- ");
            }
            result.append(" ").append(array[i]);
        }
        log(D, null, result.toString());
    }

    public static void printByteArray(String tag, byte[] array, int length) {
        StringBuilder result = new StringBuilder(tag + " byte array start--------------------------------------------------");
        if (array == null) {
            return;
        }
        int len = Math.min(length, array.length);
        for (int i = 0; i < len; i++) {
            if (i % 16 == 0) {
                result.append(" \n ");
            }
            result.append(String.format(" 0x%02x ", array[i]));
        }
        log(D, null, result.toString());
    }

    public static void printShortArray(String TAG, short[] array, int lineSize) {
        StringBuilder result = new StringBuilder(TAG + " ");
        for (int i = 0; i < array.length; i++) {
            if (i % lineSize == 0) {
                result.append(" \n ");
            }
            result.append(" ").append(array[i]);
        }

        log(D, null, result.toString());
    }

    /**
     * Print the configured log.
     */
    private static void printLog(int type, int stack, String tag, Object msg) {
        Logger.Builder builder = new Logger.Builder();
        if (tag != null) {
            builder.tag(tag);
        }
        if (stack > 0) {
            builder.t();
            builder.st(stack);
        } else {
            builder.nt();
            builder.nst();
        }
        // Print the log to view, logcat and file.
        if (FILE_PRINTER != null) {
            builder.printers(new AndroidPrinter(), FILE_PRINTER);
        } else {
            builder.printers(new AndroidPrinter());
        }
        Logger logger = builder.build();
        switch (type) {
            case V:
                logger.v(msg);
                break;
            case D:
                logger.d(msg);
                break;
            case I:
                logger.i(msg);
                break;
            case W:
                logger.w(msg);
                break;
            case E:
                logger.e(msg);
                break;
        }
    }
}
